/******************************************************************************
 * Author:      671643387
 * Created:     2016/9/26
 *****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
//>> 导入库
require('./global.js');
var fs          = require('fs');
var http        = require('http');
var url         = require('url');
var util        = require('util');
var logger      = require('./logger.js');
global.config   = require(require('fs').existsSync('../config.js') ? '../config.js' : './config.js');
var server      = require('./server.js');

///////////////////////////////////////////////////////////////////////////////
//>> 全局变量
global.gDBPlat = null;
global.gDBUser = null;
global.gUsers = {};

///////////////////////////////////////////////////////////////////////////////
//>> 程序入口
function main(){
    // 初始化日志
    logger.init();

    // 加载配置
    server.loadConf('mahjong');
    // 连接数据库
    server.loadDB(function(db){
        LOG('MongoDB connected');

        global.gDBPlat = db.collection('plat');
        global.gDBUser = db.collection('user');

        var cursor = gDBPlat.find();
        cursor.each(function(err, item) {
            if (err) {
                ERROR(err);
                process.exit(-1);
            }

            if (item) {
                gUsers[item._id] = item.uid;
            }

            if (cursor.isClosed()) {
                // 启动网络服务器
                startWebServer();
            }
        });
    });
}
main();

///////////////////////////////////////////////////////////////////////////////
//>> 功能函数

/**
 * 启动WSS服务器
 */
function startWebServer() {
    var httpServer = http.createServer(function(req, res){
        if (req.method == 'POST') {
            req.connection.destroy();
            return;
        }

        var reqObj = url.parse(req.url, true);
        var query = reqObj.query || {};
        var path = reqObj.pathname;

        req.on('end', function() {
            handleReq(query, res);
            if (query.act == 'login') {
                LOG(util.format('LOGIN: %s %s', query.openid, req.connection.remoteAddress));
            }
        });

        req.resume();
    });

    var pidFile = 'gateway.pid';

    httpServer.listen(config.GatewayPort, config.GatewayHost, function(){
        INFO('gateway start');
        fs.writeFileSync(pidFile, process.pid, 'utf8');
    });

    process.on('SIGINT', exit);
    process.on('SIGTERM', exit);

    process.on('uncaughtException', function(err) {
        ERROR(err.stack);
        if (err.code == 'EADDRINUSE') {
            exit();
        }
    });

    function exit() {
        INFO('gateway shutdown');
        fs.existsSync(pidFile) && fs.unlinkSync(pidFile);
        process.exit();
    }
}

/**
 * 处理请求
 * @param query
 * @param res
 */
function handleReq(query, res) {
    var code = 1;
    var desc = '';
    if (!query.act) {
        desc = 'no act';
    } else if (!logic[query.act]) {
        desc = 'act ' + query.act + ' not support';
    } else {
        code = 0;
    }

    var resp = {
        'code': code,
        'desc': desc,
        'data': {}
    };

    if (resp.code != 0) {
        onReqHandled(res, resp);
    } else {
        logic[query.act](query, res, resp);
    }
}

/**
 * 请求处理完毕
 * @param res
 * @param data
 */
function onReqHandled(res, data) {
    if (data.code) {
        LOG(data.desc);
    }
    res.end(JSON.stringify(data));
}

var logic = {};
/**
 * 处理用户登录
 * @param req
 * @param res
 * @param resp
 */
logic.login = function(req, res, resp) {
    do {
        if (!req.openid) {
            resp.code = 1;
            resp.desc = 'no openid';
            break;
        }
    } while (false);

    if (resp.code != 0) {
        onReqHandled(res, resp);
        return;
    }

    var openid = req.openid;
    if(gUsers.hasOwnProperty(openid)) {
        onLogIn(req, res, resp, gUsers[openid]);
    } else {
        // 注册新用户
        gDBPlat.findOneAndUpdate({_id: '_userid'}, {$inc: {'ai': 1}}, {'returnOriginal': false}, function(err, result) {
            if (!err) {
                var newUID = result.value.ai;
                gDBPlat.insertOne({_id: openid, uid: newUID, time: Date.getStamp()}, function(err, result) {
                    if (err) {
                        resp.code = 1;
                        resp.desc = 'on create';
                        onReqHandled(res, resp);
                    } else {
                        gUsers[openid] = newUID;
                        onLogIn(req, res, resp, newUID);
                    };
                });
            } else {
                resp.code = 1;
                resp.desc = 'generate id';
                onReqHandled(res, resp);
            }
        });
    }
};

logic.hasUser = function(req, res, resp) {
    if (!req.openid) {
        resp.code = 1;
        resp.desc = 'no openid';
        onReqHandled(res, resp);
        return;
    }

    var openid = req.openid;

    resp.code = 0;
    resp.data = gUsers.hasOwnProperty(openid) ? true : false;
    onReqHandled(res, resp);
};

logic.queryResource = function(req, res, resp) {

    do {
        if (!req.openid) {
            resp.code = 1;
            resp.desc = 'no openid';
            break;
        }

        var openid = req.openid;

        var existUid = gUsers[openid];
        if (!existUid) {
            resp.code = 1;
            resp.desc = 'no such user';
            break;
        }

        // 请求game数据
        var url = util.format('%s?mod=gm&act=queryResource&uid=%d&args=%j',
            getGameServer(existUid), existUid, {
                name: 'card'
            });
        httpGet(url, function(data) {
            resp.code = data.code;
            resp.desc = data.desc;
            resp.data = data.data;
            onReqHandled(res, resp);
        }, true);
        return;
    } while (false);

    onReqHandled(res, resp);
};

logic.addResource = function(req, res, resp) {

    do {
        if (!req.openid1) {
            resp.code = 1;
            resp.desc = 'no openid';
            break;
        }

        if (isNaN(req.num)) {
            resp.code = 1;
            resp.desc = 'invalid args';
            break;
        }

        var openid1 = req.openid1;
        var openid2 = req.openid2;
        var num = +req.num;

        var existUid1 = gUsers[openid1];
        if (!existUid1) {
            resp.code = 1;
            resp.desc = 'no such user 1';
            break;
        }
        var existUid2 = 0;
        if (openid2) {
            existUid2 = gUsers[openid2];
            if (!existUid2) {
                resp.code = 1;
                resp.desc = 'no such user 2';
                break;
            }
        }

        // 请求game数据
        var url = util.format('%s?mod=gm&act=addResource&uid=%d&args=%j',
            getGameServer(existUid1), existUid1, {
                num: num,
                targetUid: existUid2,
            });

        httpGet(url, function(data) {
            resp.code = data.code;
            resp.desc = data.desc;
            resp.data = data.data;
            onReqHandled(res, resp);
        }, true);
        return;
    } while (false);

    onReqHandled(res, resp);
};

logic.setNotice = function(req, res, resp) {
    var notice = req.notice || "";
    var charge = "充值请联系GM!";
    fs.writeFile('info.json', JSON.stringify({
        "charge": charge,
        "notice": notice,
    }), 'utf8');
    onReqHandled(res, resp);
};

function onLogIn(req, res, resp, uid) {
    resp.data.uid = uid;
    resp.data.game_server = getGameServer(uid);
    onReqHandled(res, resp);
}

global.getGameServer = function(uid) {
    return util.format('http://%s:%s/', config.GameHost, config.GamePort);
};